﻿using System;
using System.Threading;
using System.Threading.Tasks;
using log4net;
using SDCloudSolution.SDCloud.BusinessLayer.Model.Interfaces;
using SDCloudSolution.SDCloud.Entities.Models;
using SDCloudSolution.SDCloud.ModelRunAgent.Infrastructure.Interfaces;

namespace SDCloudSolution.SDCloud.ModelRunAgent.Infrastructure
{
    public class ModelQuequeListener : IModelQuequeListener
    {
        private readonly IModelRunComponent _modelRunComponent;
        private readonly IModelExecutorComponent _modelExecutorComponent;
        private readonly ILog _logger;

        public bool IsStopped { get; set; }

        public ModelQuequeListener(IModelRunComponent modelRunComponent, IModelExecutorComponent modelExecutorComponent, ILog logger)
        {
            IsStopped = false;
            _modelRunComponent = modelRunComponent;
            _modelExecutorComponent = modelExecutorComponent;
            _logger = logger;
        }

        public async Task Listen()
        {
            _logger.Info("Model queque lister started");
            while (!IsStopped)
            {
                var modelRunEntity = await _modelRunComponent.EnquequeModelRunAsync();
                if (modelRunEntity != null)
                {
                    _logger.Info($"New model for executing is arrived: [{modelRunEntity.ModelId}]");

                    modelRunEntity.Status = ModelRunStatus.Waiting;
                    modelRunEntity.StartDateUtc = DateTime.UtcNow;
                    await _modelRunComponent.UpdateModelRunAsync(modelRunEntity);

                    try
                    {
                        await _modelExecutorComponent.ExecuteModel(modelRunEntity);

                        _logger.Info($"Model [{modelRunEntity.ModelId}] execution complete");
                    }
                    catch (Exception e)
                    {
                        modelRunEntity.Status = ModelRunStatus.Error;
                        modelRunEntity.StartDateUtc = DateTime.UtcNow;
                        await _modelRunComponent.UpdateModelRunAsync(modelRunEntity);

                        _logger.Error($"Model [{modelRunEntity.ModelId}] execution crashed", e);
                    }
                }
                else
                {
                    Thread.Sleep(5000);
                }
            }
            _logger.Info("Model queque listener shutdowned");
        }
    }
}
